在 Windows 下使用 vim grep 的正确姿势

首先, 开发环境是Windows,
然后, 我又是一个信仰坚定的Vimer,
所以就出现了Windows + Gvim这个有些不太协调的组合, 想在盖茨叔叔的视窗OS上稍微正常的使用Gvim还是有些小麻烦, 可是这都难不倒一个有信仰的Vimer.

PS 如果你使用Osx or Linux, 大可不必这样折腾, 直接使用ack.vimgrep.vim吧, 简单的配置就可以搞定.

在Win上使用grep的可选方案

在Windows上使用grep搜索文本有以下几种方案:

  1. 使用grep命令, 虽是GNU下的工具, 但也有Win移植版;
  2. 使用vim内置的vimgrep命令, 速度最慢但是兼容性相对好;
  3. 使用Win下的原生命令findstr;
  4. 使用Win移植版的ack, 这种方法我没尝试过, 如果你用过了, 请一定告诉我:P

使用 grep.vim

虽然grep.vim插件也可以在Windows上使用, 插件也提供了一些Win下使用的选项, 但grep.vim这款插件调用的是grep命令, Win上没有grep, 怎么办?
后来找到了grep在Win平台的移植版: GnuWin
相关设置选项参考这里: grep.vim : Grep search tools integration with Vim , 在页面上搜索”MS-Windows”就可以看到for Windows的特殊选项.
不过,移植版的grep也有很多兼容问题, 略过不表233
什么, 你问我为什么不早说, 因为我一写博客就容易啰嗦…
好吧. 接下来说另一种使用vimgrep的方案:

使用 EasyGrep

之前有过一篇介绍: vim中的杀手级插件: EasyGrep,
EasyGrep使用的是vim内置的搜索命令vimgrep, 相比上面说的移植版grep, vimgrep 在Win上兼容性要大大好于上面的grep移植版.
不过EasyGrep提供了一个比较友好的搜索选项界面, 就像下面这个样子, 调整搜索选项是不是要比grep.vim直观许多?
EasyGrep Options
vimgrep的最大问题是搜索效率, 真的很差, 尤其你要搜索的目录里有成百上千的文件时.
这时候可以切到Chrome里刷一会知乎…
但刷完知乎后却发现vimgrep仍旧在努力的转动你的硬盘… 所以我又放弃了EasyGrep.

使用 findstr.vim

Windows下提供了一个原生命令findstr, 相当于Linux下的grep.
如果你想了解一下findstr命令的使用姿势, 可以看这里: Findstr - TechNet - Microsoft
在vim.org上也找了一个为findstr写的插件 – findstr.vim : Using MS-Windows findstr utility to search for text with Vim
看来在Windows上用Vim的可怜人儿还不少, 我觉得这款插件的作者就是一个:(
不过这插件简直可算得上朴素, 只提供了四个插件命令, 我觉得跟手动敲findstr命令行效率差不多, 可是我懒且健忘, 记不住这么多findstr参数,
等等, 刚才聊到的EasyGrep的搜索选项界面不是挺方便的嘛, 所以, 为什么不能把EasyGrep的搜索界面搬到findstr.vim上来?
恩, 对于程序员来说这并不难, vimscript似乎有些像shell和php的结合语言. 所以…

改进后的findstr.vim

靠着google和勤勉的copy, 一个带有良好人机交互的多功能findstr.vim被提交到了github上(666)
Github repository在这里: https://github.com/whatrtos/findstr.vim
findstr

在vimrc里新增一行配置:

nmap <leader>gg :VimFindstr<CR>

这样, 在普通模式按下\gg就可以愉快的使用findstr了.

参考

附: vimgrep命令

vimgrep命令格式如下:

vimgrep /搜索字符串/gj 文件

上面的gj参数都是可选的,

  • /g : 加上g参数的话, 如果一行有多个匹配, 那么这些匹配会都出现在搜索结果里, 所以一般不用加/g参数;
  • /j : 如果不加j参数, 执行完vimgrep会自动跳转到第一个匹配处, 所以一般都会加上/j参数;

比如vimgrep /keyword/j *.php表示仅在当前目录下的所有php文件里搜索”keyword”, 且不自动跳转到搜索结果.
如果也要在子目录递归搜索, **表示在当前目录以及子目录递归, 比如**/*.php

一些栗子:

  • 当前目录下递归搜索: vimgrep /字符串/j **/*.php
  • 仅当前目录, 不递归: vimgrep /字符串/g *.php
  • 如果要搜索多个文件扩展名, 用空格分开即可: vimgrep /字符串/j **/*.cpp **/*.php
  • Linux绝对路径, 递归搜索: vimgrep /字符串/j /home/user/**/*.cpp
  • Win绝对路径, 递归搜索: vimgrep /字符串/j D:\home\user/**/*.cpp

补充

@2016-08-01 发现一个问题, findstr.vim试用的是system(cmd)来执行findstr命令, 正常情况下这是没什么问题的, 但当遇到中文目录的时候, system执行的结果中的中文会变成”<3b><4a>“这样的代码. 所以搜索在中文目录会很蛋疼, 在quickfix里跳转不到正确的文件.
折中的办法是, 插件新增一个选项, 可以在使用findstr和vimgrep之间切换(最终还是没能摆脱vimgrep), 一般情况下推荐使用效率更高的findstr, 只有当遇到上面的问题时才使用”slowly but compatible”的vimgrep.

findstr迭代了几个版本, 修改了一些bug和改进易用性, 欢迎fork, 提交pr和issue:)


讲一个笑话, 从前森林里有只猴子, 为了能更方便的吃到樱桃, 所以这只猴子自己种了一棵樱桃树.